package fr.upmc.i3s.fuglmeyeranalyser.models.solutions;

import java.util.LinkedList;

import fr.upmc.i3s.fuglmeyeranalyser.exceptions.BetaNotFoundException;
import fr.upmc.i3s.fuglmeyeranalyser.exceptions.FM0NotFoundException;
import fr.upmc.i3s.fuglmeyeranalyser.exceptions.KapaNotFoundException;
import fr.upmc.i3s.fuglmeyeranalyser.exceptions.UnknownParameterException;
import fr.upmc.i3s.fuglmeyeranalyser.patients.PatientParameter;

public class SolutionList extends LinkedList<AbstractSolution> {

	private static final long serialVersionUID = 7057806211902688710L;
	
	
	/**
	 * Get an orderred list of BETA solution values for each patients.
	 * @return LinkedList<String> orderred list of values.
	 * @throws BetaNotFoundException
	 */
	public LinkedList<Double> getBetaSolutionsList() throws BetaNotFoundException {
		LinkedList<Double> values = null;
		for(ISolution sol : this) {
			// beta is the first value if exists
			if(sol.getSolutionParameterValues().size() >= 1 && sol.getSolutionParameterNames().get(0).equals("BETA")) {
				if(values == null) {
					values = new LinkedList<Double>();
				}
				values.add(sol.getSolutionParameterValues().get(0));
			} else {
				throw new BetaNotFoundException();
			}
		}
		return values;
	}
	
	/**
	 * Get an orderred list of FM0 solution values for each patients.
	 * @return LinkedList<String> orderred list of values.
	 * @throws FM0NotFoundException
	 */
	public LinkedList<Double> getFM0SolutionsList() throws FM0NotFoundException {
		LinkedList<Double> values = null;
		for(ISolution sol : this) {
			// fm0 is the second value if exists
			if(sol.getSolutionParameterValues().size() >= 2 && sol.getSolutionParameterNames().get(1).equals("FM0")) {
				if(values == null) {
					values = new LinkedList<Double>();
				}
				values.add(sol.getSolutionParameterValues().get(1));
			} else {
				throw new FM0NotFoundException();
			}
		}
		return values;
	}
	
	/**
	 * Get an orderred list of KAPA solution values for each patients.
	 * @return LinkedList<String> orderred list of values.
	 * @throws FM0NotFoundException
	 */
	public LinkedList<Double> getKapaSolutionsList() throws KapaNotFoundException {
		LinkedList<Double> values = null;
		for(ISolution sol : this) {
			// kapa is the third value if exists
			if(sol.getSolutionParameterValues().size() >= 3 && sol.getSolutionParameterNames().get(2).equals("KAPA")) {
				if(values == null) {
					values = new LinkedList<Double>();
				}
				values.add(sol.getSolutionParameterValues().get(2));
			} else {
				throw new KapaNotFoundException();
			}
		}
		return values;
	}
	
	/**
	 * Get an orderred list of parameter values for each patients,
	 * by the specified parameter name.
	 * @param parameterName the parameter name to return patients values
	 * @return LinkedList<String> orderred list of values.
	 * @throws UnknownParameterException
	 */
	public LinkedList<String> getParameterValuesBy(String parameterName) throws UnknownParameterException {
		LinkedList<String> values = null;
		for(ISolution sol : this) {
			for(PatientParameter pp : sol.getPatient().getParamsList()) {
				if(pp.getName().equals(parameterName)) {
					if(values == null) {
						values = new LinkedList<String>();
					}
					values.add(pp.getValue());
					break;
				}
			}
		}
		if(values == null) {
			throw new UnknownParameterException();
		}
		return values;
	}

	/**
	 * Get an orderred list of parameter values for each patients,
	 * at the specified index. You should know which parameter 
	 * is situated at given index.
	 * @param index the parameter index to return patients values
	 * @throws IndexOutOfBoundsException
	 * @return LinkedList<String> orderred list of values.
	 */
	public LinkedList<String> getParameterValuesAt(int index) throws IndexOutOfBoundsException {
		LinkedList<String> values = null;
		for(ISolution sol : this) {
			if(index >= sol.getPatient().getParamsList().size()) {
				throw new IndexOutOfBoundsException("Index > parameterList.size()");
			}
			if(values == null) {
				values = new LinkedList<String>();
			}
			values.add(sol.getPatient().getParamsList().get(index).getValue());
		}
		return values;
	}
	
	public String toUserString() {
		String result = "SolutionList :\n\n";
		for(AbstractSolution s : this) {
			if(s != null && s.toUserString() != null)
				result += s.toUserString() + "\n";
		}
		return result;
	}

	@Override
	public String toString() {
		String result = "SolutionList [";
		for(AbstractSolution s : this) {
			result += s.toString() + ", ";
		}
		return result.substring(0, result.length()-2) + "]";
	}
	
}
